﻿namespace DataWorks_Tools.BasicMethods
{
    public static class BasicFilesOperation
    {
        /// <summary>
        /// 返回目标文件夹下的所有子文件夹，不递归
        /// </summary>
        /// <param name="directorypath">文件夹路径</param>
        /// <returns>DirectoryInfo[]</returns>
        public static DirectoryInfo[] YXHGetSubDirectories(this string directorypath)
        {
            DirectoryInfo root = new DirectoryInfo(directorypath);
            return root.GetDirectories();
        }
        /// <summary>
        /// 返回目标文件夹下的所有指定的ext格式文件，并按文件名排序（如无此文件夹会自动创建）
        /// </summary>
        /// <param name="directorypath">文件夹路径</param>
        /// <param name="ext">指定文件扩展名</param>
        /// <returns>FileInfo[]</returns>
        public static FileInfo[] YXHGetAllextFiles(this string directorypath, string ext)
        {
            DirectoryInfo root = new DirectoryInfo(directorypath);
            if (!root.Exists)
            {
                root.Create();
            }
            //getfiles始终按照文件名排序
            FileInfo[] files = root.GetFiles(ext);
            if (files.Length > 0)
            {
                var fc = new FileComparer();
                Array.Sort(files, fc);
            }
            return files;
        }
        public static FileInfo[] YXHGetAllFiles(this string directorypath)
        {
            DirectoryInfo root = new DirectoryInfo(directorypath);
            if (!root.Exists)
            {
                root.Create();
            }
            //getfiles始终按照文件名排序
            FileInfo[] files = root.GetFiles();
            if (files.Length > 0)
            {
                var fc = new FileComparer();
                Array.Sort(files, fc);
            }
            return files;
        }

        /// <summary>
        /// 数据预测用的，根据前端的mat文件名来按顺序读取mat文件
        /// </summary>
        /// <param name="files"></param>
        /// <param name="names"></param>
        /// <returns></returns>
        public static FileInfo[] YXHFilterFilesByName(this FileInfo[] files, string[] names)
        {

            return Array.FindAll(files, file => Array.Exists(names, name => file.Name.Equals(name)))
           .OrderBy(file => Array.IndexOf(names, file.Name))
           .ToArray();
        }
        /// <summary>
        /// 数据预测用的，去除每个元素中的空格
        /// </summary>
        /// <param name="names"></param>
        /// <returns></returns>
        public static string[] YXHRemoveSpace(this string[] names)
        {
            string[] trimmedData = names.Select(str => new string(str.Where(c => !char.IsWhiteSpace(c)).ToArray())).ToArray();
            return trimmedData;
        }

        public static bool YXHFileIsZero(this string fileFullName)
        {
            bool result = false;
            //判断文件是否存在，如果不存在，直接返回 true
            if (!System.IO.File.Exists(fileFullName))
            {
                result = true;
            }//end: 如果文件存在的处理逻辑
            else
            {
                FileInfo fi;
                fi = new FileInfo(fileFullName);
                if (fi.Length / 1024 > 0)
                {
                    result = false;
                }
                else
                {
                    result = true;
                }
            }
            return result;
        }
        /// <summary>
        /// （专用于边缘采集器）查找0kb的数据，并把它替换成txt文件
        /// </summary>
        /// <param name="fileInfos">文件</param>
        public static void YXHTransferZeroCsvtoTxt(this FileInfo[] fileInfos)
        {
            if (fileInfos.Length > 0)
            {
                foreach (var item in fileInfos)
                {
                    if (item.Length == 0)
                    {
                        var txt = item.FullName.Replace("csv", "txt");
                        File.Move(item.FullName, txt);
                    }
                }
            }
        }

        /// <summary>
        /// 在代码中，我们使用files.Where(f => f.Extension == ".txt" && string.Compare(f.Name, csvFiles[i].Name, StringComparison.OrdinalIgnoreCase) > 0 && string.Compare(f.Name, csvFiles[i + 1].Name, StringComparison.OrdinalIgnoreCase) < 0).ToList()这行代码来找出在两个.csv文件之间的所有.txt文件。然后通过txtFilesToDelete.Count来判断这些.txt文件的数量是否小于5，如果是的话就删除这些文件。
        /// </summary>
        /// <param name="files"></param>
        public static void YXHDeleteTxtFiles(this FileInfo[] files)
        {
            var csvFiles = files.Where(f => f.Extension == ".csv").OrderBy(f => f.Name).ToList();
            for (int i = 0; i < csvFiles.Count - 1; i++)
            {
                var txtFilesToDelete = files.Where(f => f.Extension == ".txt" && string.Compare(f.Name, csvFiles[i].Name, StringComparison.OrdinalIgnoreCase) > 0 && string.Compare(f.Name, csvFiles[i + 1].Name, StringComparison.OrdinalIgnoreCase) < 0).ToList();

                if (txtFilesToDelete.Count < 6)
                {
                    foreach (var txtFile in txtFilesToDelete)
                    {
                        txtFile.Delete();
                    }
                }
            }
        }
        /// <summary>
        /// FindDataBetweenNames 方法接受一个 FileInfo[] od 数据集和两个名称 n1 和 n2 作为参数，然后使用 LINQ 的 SkipWhile 和 TakeWhile 方法来提取这两个名称之间的数据集，并返回结果。
        /// </summary>
        /// <param name="od"></param>
        /// <param name="n1"></param>
        /// <param name="n2"></param>
        /// <returns></returns>
        public static FileInfo[] YXHFindDataBetweenNames(this FileInfo[] od, string n1, string n2)
        {
            var query = od.SkipWhile(file => file.Name != n1)
                         .TakeWhile(file => file.Name != n2)
                         .Concat(od.Where(file => file.Name == n2))
                         .ToArray();

            return query;
        }

        /// <summary>
        /// 判断文件是否被使用
        /// </summary>
        /// <param name="filepath">文件路径</param>
        /// <returns>bool</returns>
        public static bool YXHCheckFileIsUsed(this string filepath)
        {
            bool result = false;
            //判断文件是否存在，如果不存在，直接返回 false
            if (!File.Exists(filepath))
            {
                result = false;
            }//end: 如果文件不存在的处理逻辑
            else
            {//如果文件存在，则继续判断文件是否已被其它程序使用
                //逻辑：尝试执行打开文件的操作，如果文件已经被其它程序使用，则打开失败，抛出异常，根据此类异常可以判断文件是否已被其它程序使用。
                FileStream? fileStream = null;
                try
                {
                    fileStream = File.Open(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                    result = false;
                }
                catch (IOException)
                {
                    result = true;
                }
                catch (Exception)
                {
                    result = true;
                }
                finally
                {
                    if (fileStream != null)
                    {
                        fileStream.Close();
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filepath">文件路径</param>  
        public static void YXHDeleteFile(this string filepath)
        {
            File.Delete(filepath);
        }
        /// <summary>
        /// （专用于边缘采集器）查找csv0kb的数据，并把它删除
        /// </summary>
        /// <param name="fileInfos">文件</param>
        public static void YXHDeleteZeroCsv(this FileInfo[] fileInfos)
        {
            if (fileInfos.Length > 0)
            {
                foreach (var item in fileInfos)
                {
                    if (item.Length == 0)
                    {
                        item.FullName.YXHDeleteFile();
                    }
                }
            }
        }

        /// <summary>
        ///（专用于边缘采集器） 获得需要处理的日期文件夹列表
        /// </summary>
        /// <param name="originalpath">源数据路径</param>
        /// <param name="combinedpath">指定的合并后的路径</param>
        /// <param name="configuredfolders">指定需要合并的日期文件夹，这是在配置文件读取到的日期数据</param>
        /// <returns></returns>
        public static DirectoryInfo[] YXHGetProcessedDateDir(string odpath, string rdpath, string[] datedir)
        {
            //获取input路径所有的子文件夹
            var subdirectorieslist = YXHGetSubDirectories(odpath);
            //获取目标路径所有的子文件夹
            var subtargetdirectorieslist = YXHGetSubDirectories(rdpath);
            //获取指定合并路径下所有已经存在的子文件夹名
            var targetlist = subtargetdirectorieslist.Select(s => s.Name).ToArray();
            DirectoryInfo[] specialdirectory;

            //如为null或者为all，则表明需要合并所有的originalpath下的子文件夹，如不为null，则表明需要合并指定的日期文件夹
            if (datedir != null && !datedir.Any(dir => dir.Contains("all", StringComparison.OrdinalIgnoreCase)))
            {
                specialdirectory = subdirectorieslist.Where(s => datedir.Contains(s.Name)).ToArray();
            }
            else
            {
                specialdirectory = subdirectorieslist;
            }
            if (targetlist.Length > 0)
            {
                //选择目标路径里没有的文件夹，如有说明之前可能已经合并过了，不需要合并，减少合并时间
                specialdirectory = specialdirectory.Where(s => !targetlist.Contains(s.Name)).ToArray();
            }
            return specialdirectory;
        }
        /// <summary>
        /// （专用于ncode转换S3T） 获得需要处理的日期文件夹列表
        /// </summary>
        /// <param name="odpath"></param>
        /// <param name="datedir"></param>
        /// <returns></returns>
        public static DirectoryInfo[] YXHGetProcessedDateDir(string odpath, string[] datedir)
        {
            //获取input路径所有的子文件夹
            var subdirectorieslist = YXHGetSubDirectories(odpath);
            DirectoryInfo[] specialdirectory;
            //如为null或者为all，则表明需要合并所有的originalpath下的子文件夹，如不为null，则表明需要合并指定的日期文件夹
            if (datedir != null && !datedir.Contains("all"))
            {
                specialdirectory = subdirectorieslist.Where(s => datedir.Contains(s.Name)).ToArray();
            }
            else
            {
                specialdirectory = subdirectorieslist;
            }
            return specialdirectory;
        }
        /// <summary>
        /// 用于报文转csv，根据月份和天来筛选文件夹（即忽略年份部分）
        /// </summary>
        /// <param name="odpath"></param>
        /// <param name="datedir"></param>
        /// <returns></returns>
        public static DirectoryInfo[] YXHGetProcessedDateDirforDBCMessage(string odpath,  string[] datedir)
        {
            //获取用户路径所有的子文件夹，如[2025-10-01,2025-10-02]
            var subdirectorieslist = YXHGetSubDirectories(odpath);
            // 将 datedir 中的日期格式化为与 data 中的文件夹名匹配的格式（MM-dd）
            var formattedDates = datedir.Select(date => date.Replace("_", "-")).ToArray();
            DirectoryInfo[] specialdirectory;
           
            //如为null或者为all，则表明需要合并所有的originalpath下的子文件夹，如不为null，则表明需要合并指定的日期文件夹
            if (datedir != null && !datedir.Any(dir => dir.Contains("all", StringComparison.OrdinalIgnoreCase)))
            {            
                // 筛选出 data 中符合格式化后的日期（仅匹配月份和天）的文件夹
                specialdirectory = subdirectorieslist.Where(dir =>
                {
                    // 只比较月份和天，忽略年份部分
                    var folderDate = dir.Name.Substring(5); // 获取文件夹名中的 MM-dd 部分
                    return formattedDates.Contains(folderDate);
                }).ToArray();
            }
            else
            {
                specialdirectory = subdirectorieslist;
            }
            return specialdirectory;
        }


      
        /// <summary>
        /// 把一个文件数据集分成n份数据集
        /// </summary>
        /// <param name="data"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static List<FileInfo[]> DivideDataIntoParts(this FileInfo[] data, int n)
        {
            return data.Select((value, index) => new { Value = value, Index = index })
                       .GroupBy(x => x.Index % n)
                       .Select(group => group.Select(x => x.Value).ToArray())
                       .ToList();
        }

        /// <summary>
        /// 用于把斜杠转成path下的斜杠，这样就直接可以在windows地址栏中复制路径了
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns></returns>
        public static string YXHPathReplace(this string path)
        {
            if (path.Contains("\\"))
            {
                return path.Replace("\\", "/");
            }
            else
            {
                return path;
            }
        }

        /// <summary>
        /// 把原始名称改为小写，去掉空格和N
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ReName(this string data)
        {
            return data.Replace("_", "").Replace("N", "").Replace(" ", "").ToLower();
        }
        /// <summary>
        /// 把逗号改为英文
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ReComma(this string data)
        {
            return data.Replace("，", ",");
        }

        //获取csv的数据行数，不包括标题行
        public static int GetCsvRowDataCount(this string csv)
        {
            int count = File.ReadAllLines(csv).Length;
            return count == 0 ? 0:count-1 ;
        }
    }
}